/* 
    使用rxjs实现一个简易的拖拽DOM元素的功能
*/

export default function drag(id) {
    // 通过计算可视窗口边界来防止元素内容超出浏览器可视范围
    const validValue = (value, max, min) => {
        return Math.min(Math.max(value, min), max)
    }
    let dragDom = document.getElementById(id);
    //  创建需要用到的Observable实例
    let mouseDown = Rx.Observable.fromEvent(dragDom, "mousedown");
    let mouseUp = Rx.Observable.fromEvent(window, "mouseup");
    let mouseMove = Rx.Observable.fromEvent(window, "mousemove");
    /*  
        1. 使用实例mouseDown，开始执行拖拽逻辑
        2. 通过map方法返回mouseMove实例并约定在触发mouseUp实例时触发complete
        3. 通过concatAll方法把所有mouseMove链接在同一个Marble diagrams中
        4. 拿到每次mouseMove的event对象获取鼠标坐标并返回给observer
    */
    // mouseUp.subscribe(console.log)
 
    let dragSource = mouseDown
        // 过滤什么时候需要做拖动
        .filter(() => { // filter方法只会在函数条件为true时返回observable
            console.log(dragDom.className);
            
            return dragDom.className === 'video-fixed'
        })
        .map((event) => { 
           return mouseMove.takeUntil(mouseUp)
        })
        .concatAll()
        // 使用withLatestFrom方法优化鼠标在dom中的位置
        // withLatestFrom： 当触发mouseMove时，来获取mouseDown的事件对象
        // 它返回的Observable的执行时机在主Observable送出新的值时执行，附属的Observable送出值时不会被调用,但是可以在执行时拿到附属目前送出的值
        // combineLatest: 当主副Observable送出最新的值时都会被执行（必须都有送出的值）。
        .withLatestFrom(mouseDown, (moveEvent, downEvent) => {
            const {width, height} = dragDom.getBoundingClientRect()
            console.log(width, height);
            return {
                x: validValue(moveEvent.clientX - downEvent.offsetX, window.innerWidth - width, 0 ),
                y: validValue(moveEvent.clientY - downEvent.offsetY, window.innerHeight - height, 0 )
            }
        })
        // .map((event) => {
        //     return {
        //         x: event.clientX - disx,
        //         y: event.clientY - disy,
        //     };
        // });

    dragSource.subscribe({
        next(val) {
            dragDom.style.left = val.x + "px";
            dragDom.style.top = val.y + "px";
        },
    });
}
